"""
@author:王耀
@date:2021/9/20
"""

import cv2
import numpy as np

def get3GaryValue(res, size, H, W, h, w, maxsize):
    """
    作用：获得当前size * size区域内的Fmid Fmax Fmin，如果Fmin < Fmed < Fmax，则返回Fmid；否则size + 2

    size:中值滤波的大小
    H，W：待滤波图片的长、宽
    h，w：当前像素的位置

    返回：自动获得的当前位置通过滤波后的像素
    """
    center = size // 2

    # 首先是对窗口内计算Fmin Fmax Fmed
    src = res[h - center: h + center + 1, w - center: w + center + 1]
    Fmin = np.min(src)
    Fmax = np.max(src)
    Fmed = np.median(src)

    if (Fmed > Fmin) and (Fmed < Fmax):  # 如果Fmin < Fmed < Fmax，则返回Fmid
        if (res[h, w] > Fmin) and (res[h, w] < Fmax):  # 如果在最大最小值中间，那么代表着它不是噪声，直接返回
            return res[h, w]
        else:
            return Fmed #如果它就是最大最小值，那么返回中间值
    else:
        size += 2 # 滤波窗口变大
        if size > maxsize: # 出现窗口越界
            return Fmed
        else:
            return get3GaryValue(res, size, H, W, h, w, maxsize) # 递归



def adapt_mid_filter(img):
    if img is None:
        raise Exception('input image ERROR!')

    if len(img.shape) == 2:
        H, W = img.shape
    else:
        raise Exception('RBG images cannot be entered in adaptive medium Filter at this time!')

    size = 3  # 初始的窗口大小
    maxsize = 11 # 最大窗口大小
    center = maxsize // 2

    res = np.zeros((H + center * 2, W + center * 2), dtype=np.float)

    res[center: center + H, center: center + W] = img.copy().astype(np.float)
    restmp = res.copy()

    for h in range(H):
        for w in range(W):
            res[center + h, center + w] = get3GaryValue(restmp, size, H, W, center + h, center + w, maxsize)

    res = np.clip(res, 0, 255)
    res = res[center: center + H, center: center + W].astype(np.uint8)

    print('执行完毕：自适应中值滤波')
    return res